package com.sdy.hospitalguard.web.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.hospitalguard.biz.dto.*;
import com.sdy.hospitalguard.biz.model.*;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.hospitalguard.biz.utils.CardAnalysis;
import com.sdy.mvc.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: 王越洋
 * @version: v1.0
 * @description: com.sdy.hospitalguard.web.controller
 * @date:2020/5/26
 */
@Slf4j
@RestController
@RequestMapping("/patient")
@Api(tags = "患者管理接口")
public class PatientAdministrationController extends BaseController {
    @Autowired
    private PatientInformationService patientInformationService;
    @Autowired
    private InpatientAreaService inpatientAreaService;
    @Autowired
    private RegulationsService regulationsService;
    @Autowired
    private HospitalUserService hospitalUserService;
    @Autowired
    private SickbedService sickbedService;
    @Autowired
    private BuildingService buildingService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;
    @Autowired
    private VisitAppointmentService visitAppointmentService;
    @Autowired
    private MatchingPeopleService matchingPeopleService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private ManagerService managerService;

    @GetMapping("/patienPageQuery")
    @ApiOperation(value = "患者分页查询", response = PatientPcDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "content", value = "姓名/住院号"),
            @ApiImplicitParam(dataType = "Integer", name = "areaId", value = "病区ID"),
            @ApiImplicitParam(dataType = "String", name = "date", value = "入院日期"),
    })
    public Response patienPageQuery(HttpServletRequest request, Page page, String content, Integer areaId, String startDate, String endDate) throws UnsupportedEncodingException, BizException {
        if (null != content) {
            content = URLDecoder.decode(content, StandardCharsets.UTF_8.name());
        }
        if (null != startDate) {
            startDate = URLDecoder.decode(startDate, StandardCharsets.UTF_8.name());
        }
        if (null != endDate) {
            endDate = URLDecoder.decode(endDate, StandardCharsets.UTF_8.name());
        }
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前用户已失效!");

        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        Page<PatientPcDTO> patientPcDTOPage = patientInformationService.patienPageQuery(page, content, areaId, startDate, endDate);
        List<PatientPcDTO> records = patientPcDTOPage.getRecords();
        for (PatientPcDTO p : records) {
            String s = regulationsService.selectEscortAssociatedRule(p.getId());
            p.setEscorNumber(Integer.parseInt(s));
        }
        patientPcDTOPage.setRecords(records);
        return Response.success(patientPcDTOPage);
    }

    @GetMapping("/excelExport")
    @ApiOperation(value = "患者Excel导出", response = PatientPcDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "content", value = "姓名/住院号"),
            @ApiImplicitParam(dataType = "Integer", name = "areaId", value = "病区ID"),
            @ApiImplicitParam(dataType = "String", name = "date", value = "入院日期"),
    })
    public void excelExport(HttpServletRequest request, HttpServletResponse response, String content, Integer areaId, String startDate, String endDate) throws IOException, BizException {
        if (null != content) {
            content = URLDecoder.decode(content, StandardCharsets.UTF_8.name());
        }
        if (null != startDate) {
            startDate = URLDecoder.decode(startDate, StandardCharsets.UTF_8.name());
        }
        if (null != endDate) {
            endDate = URLDecoder.decode(endDate, StandardCharsets.UTF_8.name());
        }
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前用户已失效!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        List<PatientPcDTO> patientPcDTOPage = patientInformationService.patienPageQuery(content, areaId, startDate, endDate);
        for (PatientPcDTO p : patientPcDTOPage) {
            String s = regulationsService.selectEscortAssociatedRule(p.getId());
            p.setEscorNumber(Integer.parseInt(s));
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String datetime = sdf.format(new Date());
        String fileName = datetime + "患者信息.xlsx";
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
        EasyExcel.write(response.getOutputStream(), PatientPcDTO.class).sheet("患者信息").doWrite(patientPcDTOPage);
    }

    @GetMapping("/inpatientAreaMessage")
    @ApiOperation(value = "病区信息", response = InpatientArea.class)
    public Response inpatientAreaMessage() {
        List<InpatientArea> list = inpatientAreaService.lambdaQuery()
                .select(InpatientArea::getId, InpatientArea::getName)
                .groupBy(InpatientArea::getId)
                .list();
        return Response.success(list);
    }


    @PostMapping("/savePatien")
    @ApiOperation(value = "新增患者", response = PatientAddedDTO.class)
    public Response savePatien(@RequestBody PatientAddedDTO patientAddedDTO) throws Exception {
        HospitalUser userByIdCard = hospitalUserService.getUserByIdCard(patientAddedDTO.getIdCard());
        List<PatientInformation> list1 = patientInformationService.lambdaQuery()
                .eq(PatientInformation::getAdmissionNumber, patientAddedDTO.getAdmissionNumber())
                .eq(PatientInformation::getPatientState, 0)
                .list();
        Assert.isTrue(list1.size() > 0, "住院号已存在!");
        boolean save1 = false;
        if (userByIdCard == null) {
            HospitalUser hospitalUser = CardAnalysis.getCard(patientAddedDTO.getIdCard())
                    .setPhone(patientAddedDTO.getPhone())
                    .setName(patientAddedDTO.getPatientName())
                    .setCreateTime(new Date());
            boolean save = hospitalUserService.save(hospitalUser);
            if (save) {
                Sickbed byId = sickbedService.getById(patientAddedDTO.getSickbedId());
                InpatientArea area = inpatientAreaService.getById(byId.getAreaId());
                PatientInformation p = new PatientInformation()
                        .setUserId(hospitalUser.getId())
                        .setSickbedId(patientAddedDTO.getSickbedId())
                        .setFloorId(String.valueOf(area.getBuildingId()))
                        .setAdmissionNumber(patientAddedDTO.getAdmissionNumber())
                        .setPatientState(0)
                        .setAdmissionTime(new Date())
                        .setCreateTime(new Date());
                save1 = patientInformationService.save(p);
                boolean a = sickbedService.lambdaUpdate()
                        .eq(Sickbed::getId, patientAddedDTO.getSickbedId())
                        .set(Sickbed::getState, 1)
                        .update();
                Assert.notTrue(a, "床位修改失败!");
            } else {

                Assert.notTrue(save, "用户创建失败!");
            }
        } else {
            boolean pa = patientInformationService.lambdaQuery()
                    .eq(PatientInformation::getUserId, userByIdCard.getId())
                    .eq(PatientInformation::getPatientState, 0)
                    .count() > 0;
            if (pa) {
                Assert.isTrue(pa, "此患者已存在!");
            } else {
                Sickbed byId = sickbedService.getById(patientAddedDTO.getSickbedId());
                InpatientArea area = inpatientAreaService.getById(byId.getAreaId());
                PatientInformation p = new PatientInformation()
                        .setUserId(userByIdCard.getId())
                        .setSickbedId(patientAddedDTO.getSickbedId())
                        .setFloorId(String.valueOf(area.getBuildingId()))
                        .setAdmissionNumber(patientAddedDTO.getAdmissionNumber())
                        .setPatientState(0)
                        .setAdmissionTime(new Date())
                        .setCreateTime(new Date());
                save1 = patientInformationService.save(p);
                boolean update = sickbedService.lambdaUpdate().eq(Sickbed::getId, patientAddedDTO.getSickbedId())
                        .set(Sickbed::getState, 1)
                        .update();
                Assert.notTrue(update, "床位修改失败!");
            }
        }
        return Response.success(save1);
    }

    @GetMapping("/getTree")
    @ApiOperation(value = "获取医院病区病房Tree", response = BuildingDTO.class)
    @ApiImplicitParam(dataType = "Integer", name = "type", value = "0:楼 1:病区 2:病房 3:楼/病区 4:楼/病区/病房")
    public Response getTree(HttpServletRequest request, Integer type) throws BizException {
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前用户已失效!");

        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        List<BuildingDTO> buildings = buildingService.queryBuilding(areaId);
        for (BuildingDTO b : buildings) {
            b.setTreeId("b" + b.getId());
        }
        if (type == 0) {
            return Response.success(buildings);
        }
        List<InpatientAreaDTO> inpatientAreas = inpatientAreaService.queryInpatientArea(areaId);
        for (InpatientAreaDTO i : inpatientAreas) {
            i.setTreeId("i" + i.getId());
        }
        if (type == 1) {
            return Response.success(inpatientAreas);
        }
        List<SickbedDTO> sickbeds = sickbedService.querySickbed(areaId);
        for (SickbedDTO s : sickbeds) {
            s.setTreeId("s" + s.getId());
        }
        if (type == 2) {
            return Response.success(sickbeds);
        }
        boolean a = true;
        for (BuildingDTO b : buildings) {
            if (b.getChildren() == null) {
                b.setChildren(new ArrayList<InpatientAreaDTO>());
            }
            for (InpatientAreaDTO i : inpatientAreas) {
                if (b.getId().equals(i.getBuildingId())) {
                    b.getChildren().add(i);
                }
                if (type == 4) {
                    if (a) {
                        for (SickbedDTO s : sickbeds) {
                            if (i.getChildren() == null) {
                                i.setChildren(new ArrayList<SickbedDTO>());
                            }
                            if (i.getId().equals(s.getAreaId())) {
                                i.getChildren().add(s);
                            }
                        }
                    }
                } else {

                }
            }
            a = false;
        }
        return Response.success(buildings);
    }

    @GetMapping("/patienDetails")
    @ApiOperation(value = "查看患者详情", response = PatientPcDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "id", value = "患者ID"),
    })
    public Response patienDetails(Integer id) throws BizException {
        Assert.isNull(id, "患者ID为空!");
        PatientPcDTO patientPcDTO = patientInformationService.patienDetails(id);
        Assert.isNull(patientPcDTO, "无患者信息!");
        String s = regulationsService.selectEscortAssociatedRule(patientPcDTO.getId());
        patientPcDTO.setEscorNumber(Integer.parseInt(s));
        return Response.success(patientPcDTO);
    }


    @GetMapping("/patienEscortList")
    @ApiOperation(value = "患者陪护列表", response = HospitalUser.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "id", value = "患者ID"),
    })
    public Response patienEscortList(Integer id) throws BizException {
        Assert.isNull(id, "患者ID为空!");
        List<HospitalUser> list = patientInformationService.patienEscortList(id);
        return Response.success(list);
    }

    @GetMapping("/patienVisitPage")
    @ApiOperation(value = "患者探视记录", response = VisitRecordDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "id", value = "患者ID"),
    })
    public Response patienVisitPage(Page page, Integer id) {
        Page<VisitRecordDTO> visitRecordDTOPage = patientInformationService.patienVisitPage(page, id);
        List<VisitRecordDTO> records = visitRecordDTOPage.getRecords();
        if (records.size() > 0) {
            for (VisitRecordDTO v : records) {
                v.setVisitTime(v.getVisitDate() + " " + cutOutTime(v.getVisitStartTime()) + "-" + cutOutTime(v.getVisitEndTime()));
            }
            visitRecordDTOPage.setRecords(records);
        }
        return Response.success(visitRecordDTOPage);
    }


    @PostMapping("/updPatienEscorRule")
    @ApiOperation(value = "修改患者陪护规则")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "id", value = "患者ID"),
            @ApiImplicitParam(dataType = "String", name = "value", value = "陪护规则"),
    })
    public Response updPatienEscorRule(Integer id, String value) throws BizException {
        Assert.isNull(id, "患者ID为空!");
        Assert.isNull(value, "规则不能为空!");
        regulationsService.updateEscortAssociatedRule(id, value);
        return Response.success();
    }


    @PostMapping("/patienDischarge")
    @ApiOperation(value = "患者出院办理")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "id", value = "患者ID"),
    })
    public Response patienDischarge(Integer id) throws BizException {
        Assert.isNull(id, "id不能为空!");
        PatientInformation byId = patientInformationService.getById(id);
        List<EscortAssociated> list = escortAssociatedService.lambdaQuery()
                .eq(EscortAssociated::getPatientId, id)
                .eq(EscortAssociated::getAttendantState, 0)
                .eq(EscortAssociated::getFlowState, 0)
                .eq(EscortAssociated::getStatus, 0)
                .list();
        for (EscortAssociated e : list) {
            MatchingPeopleDTO matchingPeopleDTO = new MatchingPeopleDTO();
            matchingPeopleDTO.setUserId(e.getUserId());
            matchingPeopleDTO.setPatientId(e.getPatientId());
            matchingPeopleDTO.setBuilding(byId.getFloorId());
            boolean success = matchingPeopleService.delete(matchingPeopleDTO);
            Assert.notTrue(success, "解除闸机绑定失败!");
        }
        //把所有的 陪护改为失效
        boolean update = escortAssociatedService.lambdaUpdate()
                .eq(EscortAssociated::getPatientId, id)
                .set(EscortAssociated::getStatus, 1)
                .update();

        //把所有的 探视改为失效
        boolean update1 = visitAppointmentService.lambdaUpdate()
                .eq(VisitAppointment::getPatientId, id)
                .set(VisitAppointment::getStatus, 1)
                .update();

//        visitAppointmentService.lambdaUpdate().eq(Vis)
        boolean update2 = sickbedService.lambdaUpdate().eq(Sickbed::getId, byId.getSickbedId())
                .set(Sickbed::getState, 0)
                .update();
        Assert.notTrue(update2, "患者床位释放失败!");

        boolean update3 = patientInformationService.lambdaUpdate()
                .eq(PatientInformation::getId, id)
                .set(PatientInformation::getPatientState, 1)
                .update();
        return Response.success(update3);
    }

    private String cutOutTime(String time) {
        String substring = "";
        if (time != null) {
            substring = time.substring(11, 16);
        } else {
            log.error("时间格式错误!");
        }
        return substring;
    }
}
